<?php
/**
 *
 * @file View.php
 *
 * Class for the different views.
 *
 * New BSD License
 * \n
 * Copyright (c) 2010 Rpd-Team
 *
 * @namespace  rpd
 * @since      0.0.1
 */

/**
 * Represents an output
 * @since  0.0.1
 *
 * A View is one of the three important parts of MVC. While the Model stores
 * information and the Controller acts on user input - the View defines how
 * to show these things to the client.
 *
 * In common the view is stored within the folder "/app/View" as a HTML file
 * which contains some fields that can be replaced by the Controller. An
 * example will follow.
 *
 * @section CHANGELOG
 *
 * <table>
 * 	<tr>
 * 		<th>Version</th>
 * 		<th>Description</th>
 *  </tr>
 *  <tr><td>0.0.9</td><td>View::getFile() delivers the used file</td></tr>
 * </table>
 *
 *
 * @section Examples
 *
 * @subsection View_DefineUse Define and use View
 * First define how information should be shown with a new PHP located in
 * "/app/View". Let's use the default "/app/View/index.php":
 * @code
 * <html>
 * <head><title>First View</title></head>
 * <body>
 * 	Hello <?=$the_name?>!
 * </body>
 * </html>
 * @endcode
 *
 * We already added a variable called "the_name" here, which can be set in
 * the according Controller within "/app/Controller". Ours need to be
 * "/app/Controller/index.php":
 * @code
 * $foo = new View();			// get a new output
 * $foo->the_name = "World";	// store some data in it
 *
 * echo $foo;					// output
 * @endcode
 *
 * @see Controller
 * @see Model
 */
class View implements Pipeline {

	protected $_file;
	protected $_map = array();

	function __call($func, $args)
	{
		$o = $this->$func;
		return $o($args[0]);
	}

	/**
	 * Get a variable of the View
	 * \code
	 * 	$view = new View();
	 * 	echo $view->foo; // will call $view->_get("foo");
	 * \endcode
	 * If the variable doesn't exists it will lookup the file and include it.
	 * Let's say:
	 *  - app\View\subpage\subpage.php
	 *  - app\View\subpage\foo.php
	 * \code
	 *   // subpage.php:
	 *
	 *   $view = new View();
	 *   echo $view->foo;
	 *   // variable hasn't been set so "app\View\subpage\foo.php" is included
	 * \endcode
	 * @param string $item
	 */
	function __get($item)
	{
		if (!isset($this->_map[$item]))
		{
			$dir  = dirname($this->_file);
			if ($dir != ".")
			{
				$dir .= "/";
			}
			else
			{
				$dir = "";
			}

				$this->_map[$item] = new View($dir . $item);
		}
		return $this->_map[$item];
	}

	function __invoke($in = NULL)
	{
		if (is_array($in))
		{
			$this->_map = array_replace(
		               		$this->_map,
		               		$in
			);
		}
		else if ($in instanceof Iterator)
		{
			$r = "";
			foreach ($in as $set)
			{
				$r .= (string) $this->__invoke($set);
			}

			return $r;
		}

		return $this;
	}

	/**
	 * Set variable of the View
	 * \code
	 * 	$view = new View();
	 * 	$view->foo = "bar";	// will call $view->_set("foo", "bar")
	 * \endcode
	 * @param string $item
	 * @param string $value
	 */
	function __set($item, $value)
	{
		$this->_map[$item] = $value;
	}


	/**
	 * Dispatch the choosen file
	 * @return string
	 */
	function __toString()
	{
		// get the current site
		global $site;
		$this->__set("site", $site);

		// let view generate the output
		if (file_exists("app/View/" . $this->_file . ".php"))
		{
			ob_start();

			// get the variables (["name"] => "var" goes $name = "var")
			extract($this->_map, EXTR_OVERWRITE & EXTR_REFS);

			// get and return the view
			include("app/View/" . $this->_file . ".php");
			return ob_get_clean();
		}
		return "";
	}

	/**
	 * Associate file as a View
	 * @param string $file Path to the file without "app/View"
	 */
	function __construct($file = NULL) {

		if ($file === NULL)
		{
			$this->_file = DIR . FILE;
		}
		else
		{
			$this->_file = $file;
		}


		$append = Registry::get("view/append");

		if (is_array($append))
		foreach ($append as $s)
		{
			if (   $s != ""
			    && file_exists("app/View/" . $this->_file . $s . ".php")
			    )
			{
				$this->_file .= $s;
			}
		}
	}

	function getFile()
	{
		return $this->_file;
	}
}

?>